package com.redepronik.negosys.invfac.service;

import static com.redepronik.negosys.utils.Utils.presentaMensaje;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.faces.application.FacesMessage;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.redepronik.negosys.invfac.dao.LocalDao;
import com.redepronik.negosys.invfac.entity.Bodega;
import com.redepronik.negosys.invfac.entity.Bodegalocal;
import com.redepronik.negosys.invfac.entity.Local;
import com.redepronik.negosys.invfac.entity.Localempleadocargo;
import com.redepronik.negosys.rrhh.entity.Empleadocargo;
import com.redepronik.negosys.rrhh.service.EmpleadoService;

@Service
public class LocalServiceImpl implements LocalService {

	@Autowired
	private LocalDao localDao;

	@Autowired
	private EmpleadoService empleadoService;

	@Autowired
	private BodegaService bodegaService;

	private ValidatorFactory factory = Validation
			.buildDefaultValidatorFactory();
	private Validator validator = factory.getValidator();

	public void actualizar(Local local) {
		Set<ConstraintViolation<Local>> violations = validator.validate(local);
		if (violations.size() > 0)
			for (ConstraintViolation<Local> cv : violations)
				presentaMensaje(FacesMessage.SEVERITY_INFO, cv.getMessage());
		else if (localDao.comprobarIndices(Local.class, "nombre",
				local.getNombre(), String.valueOf(local.getLocalid())))
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"EL LOCAL: " + local.getNombre() + " YA EXISTE", "error",
					false);
		else {
			int c = 1;
			for (Bodegalocal bl : local.getBodegalocals())
				bl.setOrden(c++);

			localDao.actualizar(local);
			presentaMensaje(FacesMessage.SEVERITY_INFO, "MODIFICO EL LOCAL: "
					+ local.getNombre(), "error", true);
		}
	}

	public void eliminar(Local local) {
		local.setActivo(local.getActivo() ? false : true);
		localDao.actualizar(local);
		presentaMensaje(FacesMessage.SEVERITY_INFO,
				(local.getActivo() ? "ACTIVO " : "DESACTIVO ") + "EL GRUPO: "
						+ local.getNombre());
	}

	public List<Local> insertar(Local local) {
		local.setActivo(true);

		Set<ConstraintViolation<Local>> violations = validator.validate(local);
		if (violations.size() > 0)
			for (ConstraintViolation<Local> cv : violations)
				presentaMensaje(FacesMessage.SEVERITY_INFO, cv.getMessage());
		else if (localDao.comprobarIndices(Local.class, "nombre",
				local.getNombre(), String.valueOf(local.getLocalid())))
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"EL LOCAL: " + local.getNombre() + " YA EXISTE", "error",
					false);
		else {
			int c = 1;
			for (Bodegalocal bl : local.getBodegalocals())
				bl.setOrden(c++);

			localDao.insertar(local);
			presentaMensaje(FacesMessage.SEVERITY_INFO, "INSERTO EL LOCAL: "
					+ local.getNombre(), "error", true);
		}
		return obtenerTodos();
	}

	public void eliminarCajero(Localempleadocargo encargado) {
		encargado.setActivo(encargado.getActivo() ? false : true);
		presentaMensaje(FacesMessage.SEVERITY_INFO,
				(encargado.getActivo() ? "ACTIVO " : "DESACTIVO ")
						+ "EL CAJERO: "
						+ encargado.getEmpleadocargo().getEmpleado()
								.getPersona().getApellido()
						+ " "
						+ encargado.getEmpleadocargo().getEmpleado()
								.getPersona().getNombre());
	}

	public void insertarCajero(Local local, Empleadocargo cajero,
			List<Localempleadocargo> listaLocalEmpleadoCargo) {
		boolean bd = false;
		if (cajero.getEmpleadocargoid() == 0
				|| cajero.getEmpleadocargoid() == null)
			presentaMensaje(FacesMessage.SEVERITY_ERROR, "ESCOJA UN CAJERO");
		else {
			for (Localempleadocargo bec : listaLocalEmpleadoCargo)
				if (bec.getEmpleadocargo().getEmpleadocargoid() == cajero
						.getEmpleadocargoid()) {
					bd = true;
					break;
				}

			if (bd)
				presentaMensaje(FacesMessage.SEVERITY_ERROR,
						"YA EXISTE ESTE CAJERO");
			else {
				Localempleadocargo lec = new Localempleadocargo();
				lec.setLocal(local);
				lec.setEmpleadocargo(empleadoService
						.obtenerPorEmpleadoCargoId(cajero.getEmpleadocargoid()));
				lec.setActivo(true);
				listaLocalEmpleadoCargo.add(lec);
				presentaMensaje(FacesMessage.SEVERITY_INFO,
						"CAJERO ASOCIADO CORRECTAMENTE");
			}
			cajero = new Empleadocargo();
		}
	}

	public void modificarBodega(Local local, int bodega1, int bodega2) {
		Bodega oldBodega = bodegaService.obtenerPorBodegaId(bodega1);
		Bodega newBodega = bodegaService.obtenerPorBodegaId(bodega2);
		List<Bodegalocal> list = local.getBodegalocals();
		for (Bodegalocal bodegaLocal : list)
			if (bodegaLocal.getBodega().getNombre()
					.compareTo(oldBodega.getNombre()) == 0) {
				local.getBodegalocals()
						.get(local.getBodegalocals().indexOf(bodegaLocal))
						.setBodega(newBodega);
				break;
			}
	}

	public void guardarCajeros(Local local,
			List<Localempleadocargo> listaLocalEmpleadoCargo) {
		if (listaLocalEmpleadoCargo.isEmpty())
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"INGRESE POR LO MENOS UN CAJERO", "error", true);
		else {
			if (local.getLocalempleadocargos() == null)
				local.setLocalempleadocargos(new ArrayList<Localempleadocargo>());

			local.setLocalempleadocargos(listaLocalEmpleadoCargo);
			actualizar(local);
			presentaMensaje(FacesMessage.SEVERITY_INFO,
					"SE ACTUALIZÓ CON EXITO", "error", false);
		}
	}

	public List<Local> obtenerPorCajero(String cajero) {
		List<Local> list = localDao
				.obtenerPorHql(
						"select l from Local l "
								+ "inner join l.bodegalocals bl "
								+ "inner join bl.bodega b "
								+ "inner join l.localempleadocargos lec "
								+ "inner join lec.empleadocargo ec "
								+ "inner join ec.cargo c "
								+ "inner join ec.empleado e "
								+ "inner join e.persona p "
								+ "where b.activo=true and l.activo=true and lec.activo=true and ec.actual=true and c.activo=true and e.activo=true and p.activo=true and c.cargoid=4 and p.cedula=?1",
						new Object[] { cajero });
		return list;
	}

	public Local obtenerPorLocalId(Integer localId) {
		Local local = localDao.obtenerPorHql(
				"select distinct l from Local l "
						+ "inner join fetch l.bodegalocals "
						+ "where l.localid=?1 and l.activo=true",
				new Object[] { localId }).get(0);
		return local;
	}

	public List<Local> obtenerTodos() {
		List<Local> list = localDao.obtenerPorHql(
				"select distinct l from Local l left join fetch l.localempleadocargos "
						+ "left join fetch l.bodegalocals "
						+ "order by l.nombre", new Object[] {});
		return list;
	}
}